
package legumes.client.ui.widgets.form.item;

import java.util.ArrayList;
import java.util.List;

import legumes.client.services.LegumesServices;
import legumes.client.services.LegumesServicesAsync;
import legumes.client.ui.basket.slate.NewMarketProductEditionWindow;
import legumes.shared.domain.Product;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.core.Function;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.validator.CustomValidator;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.CellClickEvent;
import com.smartgwt.client.widgets.grid.events.CellClickHandler;

// *** GOOD EXAMPLE is com.smartgwt.client.widgets.form.fields.SelectOtherItem
//SelectOtherItem selectOtherItem = new SelectOtherItem();  
//selectOtherItem.setOtherTitle("Other..");  
//selectOtherItem.setOtherValue("OtherVal");  
//
//selectOtherItem.setTitle("Units");  
//selectOtherItem.setValueMap("Ea", "Pkt", "Bag", "Ctn");  
//selectOtherItem.setValueFormatter(new FormItemValueFormatter() {  
//    public String formatValue(Object value, Record record, DynamicForm form, FormItem item) {  
//        ListGridRecord r = item.getSelectedRecord();  
//        if (r == null) return "";  
//        return r.getAttribute("Name") + " (" + r.getAttribute("Email") + ")";  
//    }  
//});  

// ### MULTI SEARCH FIELD
//ListGrid pickListProperties = new ListGrid();  
//pickListProperties.setShowFilterEditor(true);  
//  
//ListGridField skuField = new ListGridField("SKU");  
//ListGridField itemNameField = new ListGridField("itemName");  
//  
//SelectItem filteredSelect = new SelectItem("filteredSelect");  
//setTitle("Item (Select)");  
//setOptionDataSource(supplyItemDS);  
//setDisplayField("itemName");  
//setValueField("SKU");  
//setPickListWidth(300);  
//setPickListFields(skuField, itemNameField);  
//setPickListProperties(pickListProperties); 
public class ProductNameAutoSuggestComboItem extends ComboBoxItem {

	public static final String NEW_PRODUCT_SUFFIX = "[Créer nouveau produit...]";
	final String SEARCH_STR = "Search!!";
	private final LegumesServicesAsync suggestService = 
		GWT.create(LegumesServices.class);
	private ListGrid pickListProperties;
	private boolean isANewProductSelected = false;
	private List<CellClickHandler> cellClickHandlerList;
	private Product[] currentProductsSuggestionsAr;
	private Product selectedProduct;
	private List<ChangedHandler> changedHandlerList;
	
	public ProductNameAutoSuggestComboItem() {
		super();
		changedHandlerList = new ArrayList<ChangedHandler>(1);
		cellClickHandlerList = new ArrayList<CellClickHandler>();
		
		setShowTitle(true);
		setTitle("Produit");
		setWidth(130);
//		setShowPickerIcon(false);
		setValueField("name");
		setDisplayField("name");
		setValue(SEARCH_STR);
		setTooltip("Rechercher un produit...");
		setCompleteOnTab(true);
		
//		setOtherTitle("Nouveau produit..");  
//		setOtherValue("NewProduct");  
//		TextItem ti = new TextItem();
//		setEditorType(ti);
		
//		setEditorValueFormatter(new FormItemValueFormatter() {  
//				    public String formatValue(Object value, Record record, DynamicForm form, FormItem item) {  
//				        ListGridRecord r = item.getSelectedRecord();//((ComboBoxItem)item).getSelectionRange()
//				        if (r == null) return value==null?"":value.toString();  
//				        GWT.log("r.getAttribute(productName) " + r.getAttribute("productName") );
//				        return r.getAttribute("productName") + " (" + r.getAttribute("productVariety") + " / " + r.getAttribute("productCategory") + ")";  
//				    }  
//				});  

		setValueField("productName");
		
		pickListProperties = new ListGrid();
		addComboListClickHandler(new CellClickHandler() {
			
			@Override
			public void onCellClick(CellClickEvent event) {
				ListGridRecord r = event.getRecord();
				int productSuggestIndex =  r.getAttributeAsInt("productSuggestIndex");
				if(productSuggestIndex<0 || productSuggestIndex>currentProductsSuggestionsAr.length){
					isANewProductSelected = r.getAttributeAsBoolean("isANewProduct");
					if(isANewProductSelected()){
						String productName = r.getAttribute("productName");
						final NewMarketProductEditionWindow nmpew = new NewMarketProductEditionWindow(productName);
						nmpew.setFctCalledOnProductCreated(new Function(){
							
							private ChangedEvent createEvent(){
								return new ChangedEvent(ProductNameAutoSuggestComboItem.this.getJsObj()){
	
									@Override
									public DynamicForm getForm() {
										return ProductNameAutoSuggestComboItem.this.getForm();
									}
	
									@Override
									public FormItem getItem() {
										return ProductNameAutoSuggestComboItem.this;
									}
	
									@Override
									public Object getValue() {
										return ProductNameAutoSuggestComboItem.this.getValue();
									}
									
								};
							}
							
							private void updateCurrentProductsSuggestionsAr(Product p_){
								Product[] pAr = new Product[currentProductsSuggestionsAr.length+1];
								int i=0;
								for(Product p :currentProductsSuggestionsAr){
									pAr[i] = p;
									i++;
								}
								pAr[i] = getSelectedProduct();
							}
							
							@Override
							public void execute() {
								Product createdProduct = nmpew.getCreatedProduct();
								if(createdProduct != null){
									selectedProduct = createdProduct;
									ProductNameAutoSuggestComboItem.this.setValue(getSelectedProduct().getName() );
									ChangedEvent ce = createEvent();
									
									updateCurrentProductsSuggestionsAr(getSelectedProduct());
									//Do not use the 1st one, because it is for filling the pick list
									for(int i=1; i<changedHandlerList.size(); i++){
										changedHandlerList.get(i).onChanged(ce);
									}
									ProductNameAutoSuggestComboItem.this.validate();
								}
							}
						});
					}
				} else {
					selectedProduct = currentProductsSuggestionsAr[productSuggestIndex];
				}
			}
		});
		pickListProperties.addCellClickHandler(new CellClickHandler() {
			
			@Override
			public void onCellClick(CellClickEvent event) {
				
				for(CellClickHandler cch : cellClickHandlerList){
					cch.onCellClick(event);
				}
				
			}
		});
//		pickListProperties.setShowFilterEditor(true);  
		
		ListGridField productNameField = new ListGridField("productName", "Produit", 300);  
		ListGridField productVarietyField = new ListGridField("productVariety", "Vari&eacute;t&eacute;", 100);  
		ListGridField productCategoryField = new ListGridField("productCategory", "Cat&eacute;gorie", 100);  
		
		setPickListWidth(500);  
		setPickListFields(productNameField, productVarietyField, productCategoryField);  
		setPickListProperties(pickListProperties);
		addChangedHandler(new ChangedHandler() {
			
			@Override
			public void onChanged(ChangedEvent event) {
				selectedProduct = null;
				String val = (String) getValue();
				getSuggestions(val);
			}
		});
//		addKeyUpHandler(new KeyUpHandler() {
//			@Override
//			public void onKeyUp(KeyUpEvent event) {
//				String val = (String) getValue();
//				GWT.log("Suggestion=" + val);
//				getSuggestions(val);
//			}
//		});
		
		CustomValidator cv = new CustomValidator(){

			@Override
			protected boolean condition(Object value) {
				return ProductNameAutoSuggestComboItem.this.getSelectedProduct()!=null;
			}
			
		};
		cv.setErrorMessage("Erreur le produit sélectionné n'existe pas. Veuillez le créer avant de valider.");
		setValidators(cv);
		getSuggestions("");
	}
	
	@Override
	public HandlerRegistration addChangedHandler(ChangedHandler ch_){
		changedHandlerList.add(ch_);
		return super.addChangedHandler(ch_);
	}
	
	public void addComboListClickHandler(CellClickHandler cch_){
		cellClickHandlerList.add(cch_);
	}
	
	public void removeComboListClickHandler(CellClickHandler cch_){
		cellClickHandlerList.remove(cch_);
	}
	
	public Product findSuggestionProduct(String preffix_){
		if ( currentProductsSuggestionsAr!=null && currentProductsSuggestionsAr.length>0){
			Product p = currentProductsSuggestionsAr[0];
			if(p.getName().equalsIgnoreCase(preffix_) ||
					p.getProductVariety().getName().equalsIgnoreCase(preffix_) ||
					p.getProductVariety().getProductCategory().getName().equalsIgnoreCase(preffix_) ){
				return p;
			}
		}
		return null;
	}
	
	private void getSuggestions(final String prefix_) {
		suggestService.getProductsStartingWith(prefix_, new AsyncCallback<Product[]>() {
			public void onSuccess(Product[] suggestions) {
				currentProductsSuggestionsAr = suggestions;
				DataSource ds = new DataSource();
				ds.setClientOnly(true);
				DataSourceTextField productNameField = new DataSourceTextField("productName", "productName");
				productNameField.setPrimaryKey(true);
				DataSourceTextField productVarietyField = new DataSourceTextField("productVariety", "productVariety");
				DataSourceTextField productCategoryField = new DataSourceTextField("productCategory", "productCategory");
				ds.setFields(productNameField, productVarietyField, productCategoryField);
				ListGridRecord record;
				GWT.log("suggestions.length=" + suggestions.length + "suggestions" + suggestions);
				Product productExists = null;
				for (int i = 0; i < suggestions.length; i++) {
					record = new ListGridRecord();
					Product curP = suggestions[i];
					String productName = curP.getName();
					record.setAttribute("productSuggestIndex", i);
					record.setAttribute("productName", productName);
					record.setAttribute("productVariety", curP.getProductVariety().getName());
					record.setAttribute("productCategory", curP.getProductVariety().getProductCategory().getName());
					ds.addData(record);
					if(productExists==null && productName.equalsIgnoreCase(prefix_)){
						productExists = curP;
					}
				}
				
				if(suggestions.length<=0 || productExists==null){
					record = new ListGridRecord();
					record.setAttribute("productSuggestIndex", -1);
					record.setAttribute("productName", prefix_);
					record.setAttribute("productVariety", NEW_PRODUCT_SUFFIX);
					record.setAttribute("productCategory", "");
					record.setAttribute("isANewProduct", true);
					
					ds.addData(record);
				} else {
					selectedProduct = productExists;
				}
				
//				else {
//					record = new ListGridRecord();
//					record.setAttribute("name", "<HR/>");
//					ds.addData(record);
//					
//					record = new ListGridRecord();
//					record.setAttribute("name", NEW_PRODUCT_SUFFIX);
//					ds.addData(record);
//				}
				setOptionDataSource(ds);
				
//				pickListProperties.setDataSource(ds);
				
				fetchData();
			}

			public void onFailure(Throwable caught) {
			}
		});
	}
	
	public String getNewProductToCreate(String actionValue_){
		String newProductToCreate = null;
		if(actionValue_ != null 
			&& actionValue_.length() > NEW_PRODUCT_SUFFIX.length()){
			newProductToCreate = actionValue_.substring(0,
						actionValue_.length() - NEW_PRODUCT_SUFFIX.length() );
		}
		
		return newProductToCreate;
	}

	public boolean isANewProductSelected() {
		return isANewProductSelected;
	}

	public Product getSelectedProduct() {
		return selectedProduct;
	}

	public void setSelectedProduct(Product product) {
		selectedProduct = product;
	}
	
	
}
